/*
 * Copyright (c) 2025 [ByteDance Ltd. and/or its affiliates.] and/or its affiliates
 * SPDX-License-Identifier: LGPL v2.1+
*/
//
// Created by 郭鹤 on 2020/4/17.
//

#include "FFAny.h"
#include <string>
#include <random>

 FFAny::~FFAny() {
    reset();
}

 FFAny::FFAny(const FFAny &other) {
    if (other.hasValue()) {
        other._value_ptr->cloneToThis(this);
    }
}

 FFAny::FFAny(FFAny &&other) noexcept : _value_ptr(other._value_ptr), _currentMemSize(other._currentMemSize) {
    other._value_ptr = nullptr;
    other._currentMemSize = 0;
}

void FFAny::swap(FFAny &rhs) noexcept {
    std::swap(_value_ptr, rhs._value_ptr);
    std::swap(_currentMemSize, rhs._currentMemSize);
}

bool FFAny::hasValue() const noexcept {
    return _value_ptr != nullptr;
}

const char* FFAny::name() const noexcept {
    return hasValue() ? _value_ptr->typeIndex.name() : "no value";
}

void FFAny::reset() {
    if (_value_ptr) {
        _value_ptr->destruct();
        delete reinterpret_cast<uint8_t *>(_value_ptr);
        _value_ptr = nullptr;
    }
    _currentMemSize = 0;
}

FFAny &FFAny::operator=(FFAny &&rhs) {
    if (this != &rhs) {
        this->swap(rhs);
        rhs.reset();
    }
    return *this;
}

FFAny &FFAny::operator=(const FFAny &rhs) {
    if (this != &rhs) {
        if (rhs.hasValue()) {
            rhs._value_ptr->cloneToThis(this);
        }
        else {
            reset();
        }
    }
    return *this;
}

std::string FFAny::toString() const {
    if (Is<int>()) {
        return std::to_string(AnyCast<int>());
    } else if (Is<bool>()) {
        if (this->AnyCast<bool>()) {
            return std::string("true");
        } else {
            return std::string("false");
        }
    } else if (Is<long>()) {
        return std::to_string(AnyCast<long>());
    } else if (Is<long long>()) {
        return std::to_string(AnyCast<long long>());
    } else if (Is<unsigned>()) {
        return std::to_string(AnyCast<unsigned>());
    } else if (Is<unsigned long>()) {
        return std::to_string(AnyCast<unsigned long>());
    } else if (Is<unsigned long long>()) {
        return std::to_string(AnyCast<unsigned long long>());
    } else if (Is<float>()) {
        return std::to_string(AnyCast<float>());
    } else if (Is<double>()) {
        return std::to_string(AnyCast<double>());
    } else if (Is<long double>()) {
        return std::to_string(AnyCast<long double>());
    } else if (Is<std::string>()) {
        return AnyCast<std::string>();
    } else {
        return {};
    }
}

bool FFAny::isSameType(const std::type_info &info) const {
    if (hasValue()) {
        std::type_index tmp(info);
        const auto &now = _value_ptr->typeIndex;
        return now == tmp || strcmp(now.name(), tmp.name()) == 0;
    }
    return false;
}

void FFAny::printErrorLog() const {
//    VELOGE("FFAny type error. %s %s", name(), toString().c_str());
//    TE_ASSERT(false);
}



template<class IntType = int>
static IntType random(IntType min, IntType max) {
    std::random_device dev;
    std::mt19937 rng(dev());
    std::uniform_int_distribution<std::mt19937::result_type> dist6(min, max);
    return dist6(rng);
}
